package com.ticket.common.utils.wechat;

import com.ticket.common.utils.wechat.sdk.MyX509TrustManager;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.CharArrayBuffer;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * 分装一个http请求的工具类
 *
 * @author 顾炜【guwei】 on 14-4-22.下午3:17
 */
public class HttpClientUtils {

    private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);

    private static HttpClientUtils instance;

    /**
     * 请求超时时间
     */
    private static final int CONST_SO_TIMEOUT_SECOND = 30;

    private HttpClientUtils() {
    }

    public static synchronized HttpClientUtils getInstance() {
        if (instance == null) {
            instance = new HttpClientUtils();
        }
        return instance;
    }
    /**
     * <p>发送POST请求
     *
     * @param url          POST请求地址
     * @param headerMap    POST请求头参数容器
     * @param parameterMap POST请求参数容器
     * @return 与当前请求对应的响应内容字
     */
    public String doPost(String url, Map<String, Object> headerMap, Map<String, Object> parameterMap) throws Exception {
        String content = null;
        CloseableHttpClient httpClient = getHttpClient();
        try {
            HttpPost postMethod = new HttpPost(url);
//            postMethod.setHeader("Content-Type", "application/json;charset=utf-8");
//            postMethod.setHeader("Accept", "application/json;charset=utf-8");

            //头部请求信息
            if (headerMap != null) {
                Iterator iterator = headerMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Entry entry = (Entry) iterator.next();
                    postMethod.addHeader(entry.getKey().toString(), entry.getValue().toString());
                }
            }

            if (parameterMap != null) {
                Iterator iterator = parameterMap.keySet().iterator();
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                while (iterator.hasNext()) {
                    String key = (String) iterator.next();
                    nvps.add(new BasicNameValuePair(key, (String) parameterMap.get(key)));
                }
                postMethod.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            }


            CloseableHttpResponse httpResponse = httpClient.execute(postMethod);
            if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                try {
                    //读取内容
                    content = EntityUtils.toString(httpResponse.getEntity());
                } finally {
                    httpResponse.close();
                }
            } else {
                throw new Exception(httpResponse.getStatusLine().getReasonPhrase());
            }
        } catch (IOException ex) {
            throw new Exception(ex.getMessage());
        } finally {
            try {
                closeHttpClient(httpClient);
            } catch (Exception e) {
                throw new Exception(e.getMessage());
            }
        }
        return content;
    }

    public CloseableHttpClient getHttpClient() {
        return HttpClients.createDefault();
    }

    private void closeHttpClient(CloseableHttpClient client) throws IOException {
        if (client != null) {
            client.close();
        }
    }

    /**
     * @param requestUrl
     * @param requestMethod
     * @param outputStr
     * @return
     * @see
     */
    public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // // 从上述SSLContext对象中得到SSLSocketFactory对象
            // SSLSocketFactory ssf = sslContext.getSocketFactory();
            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(sslContext.getSocketFactory());
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setConnectTimeout(CONST_SO_TIMEOUT_SECOND * 1000);
            conn.setReadTimeout(CONST_SO_TIMEOUT_SECOND * 1000);
            // 设置请求方式（GET/POST）
            conn.setRequestMethod(requestMethod);
            conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }
            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }
            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            conn.disconnect();
            return buffer.toString();
        } catch (ConnectException ce) {
            logger.error("连接超时：", ce);
        } catch (Exception e) {
            logger.error("https请求异常：", e);
        }
        return null;
    }

    public static String httpReqestUrl(String url, Map<String, Object> headerMap, String method, String jsonString) {
        if (method.equals("post")) {
            return postJson(url, headerMap, jsonString);
        } else if (method.equals("put")) {
            return putJson(url, headerMap, jsonString);
        } else if (method.equals("del")) {
            return delJson(url, headerMap, jsonString);
        } else {
            return "请选择请求方式！";
        }
    }

    private static String postJson(String url, Map<String, Object> headerMap, String jsonString) {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPost post = new HttpPost(url);
        if (headerMap != null) {
            Iterator iterator = headerMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry entry = (Entry) iterator.next();
                post.addHeader(entry.getKey().toString(), entry.getValue().toString());
            }
        }
        CloseableHttpResponse response = null;
        try {
            post.setEntity(new ByteArrayEntity(jsonString.getBytes("UTF-8")));
            response = httpClient.execute(post);
//            if (response != null && response.getStatusLine().getStatusCode() == 200) {
            HttpEntity entity = response.getEntity();
            result = entityToString(entity);
//            }
            return result;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private static String putJson(String url, Map<String, Object> headerMap, String jsonString) {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpPut put = new HttpPut(url);
        if (headerMap != null) {
            Iterator iterator = headerMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry entry = (Entry) iterator.next();
                put.addHeader(entry.getKey().toString(), entry.getValue().toString());
            }
        }
        CloseableHttpResponse response = null;
        try {
            put.setEntity(new ByteArrayEntity(jsonString.getBytes("UTF-8")));
            response = httpClient.execute(put);
//            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                result = entityToString(entity);
//            }
            return result;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private static String delJson(String url, Map<String, Object> headerMap, String jsonString) {
        String result = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        HttpDeleteWithBody del = new HttpDeleteWithBody(url);
        if (headerMap != null) {
            Iterator iterator = headerMap.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry entry = (Entry) iterator.next();
                del.addHeader(entry.getKey().toString(), entry.getValue().toString());
            }
        }
        CloseableHttpResponse response = null;
        try {
            if (StringUtils.isNotBlank(jsonString)) {
                del.setEntity(new ByteArrayEntity(jsonString.getBytes("UTF-8")));
            }
            response = httpClient.execute(del);
//            if (response != null && response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                result = entityToString(entity);
//            }
            return result;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    private static String entityToString(HttpEntity entity) throws IOException {
        String result = null;
        if (entity != null) {
            long lenth = entity.getContentLength();
            if (lenth != -1 && lenth < 2048) {
                result = EntityUtils.toString(entity, "UTF-8");
            } else {
                InputStreamReader reader1 = new InputStreamReader(entity.getContent(), "UTF-8");
                CharArrayBuffer buffer = new CharArrayBuffer(2048);
                char[] tmp = new char[1024];
                int l;
                while ((l = reader1.read(tmp)) != -1) {
                    buffer.append(tmp, 0, l);
                }
                result = buffer.toString();
            }
        }
        return result;
    }

}